package cn.mesmile.security.config;

import cn.mesmile.security.service.IEmployeeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;

import javax.sql.DataSource;

/**
 * @author zb
 * @date 2020/4/5 15:25
 * @Description:
 */
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true,securedEnabled=true,jsr250Enabled=true) // 开启spring security注解支持
@Configuration
public class MyWebSecurityConfig extends WebSecurityConfigurerAdapter {

    /**
     *  JSR-250注解
     *
     * @DenyAll
     * @RolesAllowed
     * @PermitAll
     * 这里面@DenyAll 代表拒绝 和 @PermitAll 代表通过
     *
     * @RolesAllowed({"ROLE_USER", "ROLE_ADMIN"}) 代表标注的方法只要具有ROLE_USER, ROLE_ADMIN任意一种权限就可以访问
     *
     *
     *  https://blog.csdn.net/qq_32867467/article/details/95078794
     *
     */

    private final IEmployeeService employeeService;

    private final DataSource dataSource;

    // 全局 权限不足异常处理
    private final AuthenticationAccessDeniedHandler authenticationAccessDeniedHandler;

    @Autowired
    public MyWebSecurityConfig(IEmployeeService employeeService, DataSource dataSource, AuthenticationAccessDeniedHandler authenticationAccessDeniedHandler) {
        this.employeeService = employeeService;
        this.dataSource = dataSource;
        this.authenticationAccessDeniedHandler = authenticationAccessDeniedHandler;
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {

        /**
         * 这里配置我们自定义的 userDetailService   employeeService是继承了UserDetailService 覆写其中的loadUserByUsername 方法，从数据库中那用户信息
         */
        auth.userDetailsService(employeeService).passwordEncoder(new BCryptPasswordEncoder());


        /*
         * 基于内存的用户登录
         */
        // 加密方式
//        PasswordEncoder passwordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
//      将用户信息存储在 内存中
//        auth.inMemoryAuthentication()
//                .passwordEncoder(passwordEncoder)
//                .withUser("admin")
//                .password(passwordEncoder.encode("123"))
//                .roles();
//
//        auth.inMemoryAuthentication()
//                .passwordEncoder(passwordEncoder)
//                .withUser("user")
//                .password(passwordEncoder.encode("123"))
//                .roles();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 自定义表单登录路径
//                http.formLogin()
//                .loginPage("/login.html")           //前端路径
//                .loginProcessingUrl("/login")       //后端请求登录api
//                .successForwardUrl("/idex.html")    //成功后前端路径
//                .failureForwardUrl("/failed.html")  //失败后前端路径
//                .permitAll()                        //释放上面比如： /login 路径
//                .and()
//                .logout()
//                .logoutUrl("/logout")   // 退出登录 api
//                .logoutSuccessUrl("/login.html") // 退出登录成功后，跳转到的页面
//                .invalidateHttpSession(true) //退出成功，是否清空session
//                .permitAll(); //释放上面比如： /logout 路径

        super.configure(http);

        // 匹配任意请求路径，一旦匹配到 这里定义的 ，就全部放行   permitAll 代表通过的意思
//        authorizeRequests().antMatchers("/authentication/require", "/login").permitAll()

                    // 任意请求都需要认证
//                .anyRequest().authenticated()

                    // 关闭 csrf
//                .and().csrf().disable()

                // 新增remember me配置信息
        http.rememberMe()
                .tokenRepository(persistentTokenRepository()) // 配置token持久化仓库
                .tokenValiditySeconds(60) // 过期时间，单位为秒
                .userDetailsService(employeeService); // 处理自动登录逻辑

        http.logout().permitAll().and().csrf().disable().exceptionHandling().accessDeniedHandler(authenticationAccessDeniedHandler);
    }

    /**
     * 开启记住我的功能
     *
     *
     *  <tr>
     *    <td colspan="2"><input type="checkbox" name="remember-me" value="true">记住我</td>
     *  </tr>
     * @return
     */
    @Bean
    public PersistentTokenRepository persistentTokenRepository() {
        JdbcTokenRepositoryImpl persistentTokenRepository = new JdbcTokenRepositoryImpl();
        persistentTokenRepository.setDataSource(dataSource);

        //自动创建数据库表，使用一次后注释掉，不然会报错
//        persistentTokenRepository.setCreateTableOnStartup(true);

        return persistentTokenRepository;
    }


}
